Django λ―Έλ€μ¨μ΄μ λν μ¬μΈ΅ λΆμ. μμ² μ²λ¦¬μμμ μν , μ₯μ , μ¬μ©μ μ μ λ―Έλ€μ¨μ΄ κ°λ° λ° μ€μ μ¬μ© μ¬λ‘λ₯Ό μ€λͺ ν©λλ€. μ μΈκ³ κ°λ°μλ₯Ό μν ν¬κ΄μ μΈ κ°μ΄λμ λλ€.
Python Django λ―Έλ€μ¨μ΄: μμ² μ²λ¦¬ νμ΄νλΌμΈ
Djangoλ κ³ κΈ Python μΉ νλ μμν¬λ‘, μΉ κ°λ°μ λν κ°λ ₯νκ³ μ°μν μ κ·Ό λ°©μμ μ 곡ν©λλ€. κΈ°λ₯μ ν΅μ¬μλ μμ μμ μμ²μ μλ―Έ μλ μλ΅μΌλ‘ λ³ννλ μΌλ ¨μ μμ μΈ μμ² μ²λ¦¬ νμ΄νλΌμΈμ΄ μμ΅λλ€. μ΄ νμ΄νλΌμΈμ μ€μν κ΅¬μ± μμλ λ―Έλ€μ¨μ΄λ‘, κ°λ°μλ μμ² μ²λ¦¬ μ€ λ€μν μ§μ μμ μ¬μ©μ μ μ λ‘μ§κ³Ό λμμ μ½μ ν μ μμ΅λλ€.
Django μμ² μ²λ¦¬ μ£ΌκΈ° μ΄ν΄
λ―Έλ€μ¨μ΄λ₯Ό μμΈν μ΄ν΄λ³΄κΈ° μ μ Django μμ²μ κΈ°λ³Έ νλ¦μ νμ νλ κ²μ΄ μ€μν©λλ€. μ¬μ©μκ° Django μ ν리μΌμ΄μ μ μμ²μ νλ©΄ μΌλ°μ μΌλ‘ λ€μ λ¨κ³κ° μνλ©λλ€.
- WSGI μλ²κ° μμ²μ μμ ν©λλ€: WSGI(Web Server Gateway Interface) μλ²(Gunicorn λλ uWSGIμ κ°μ)κ° ν΄λΌμ΄μΈνΈλ‘λΆν° HTTP μμ²μ μμ ν©λλ€.
- λ―Έλ€μ¨μ΄ μ²λ¦¬(μμ ): μμ²μ `settings.py` νμΌμ μ μλ μμλλ‘ λ―Έλ€μ¨μ΄ μ€νμ ν΅κ³Όν©λλ€. κ° λ―Έλ€μ¨μ΄ κ΅¬μ± μμλ λ·°μ λλ¬νκΈ° μ μ μμ²μ μ²λ¦¬ν κΈ°νλ₯Ό μ»μ΅λλ€. μ¬κΈ°μμ μΈμ¦, κΆν λΆμ¬, μΈμ κ΄λ¦¬ λ° κΈ°ν μ¬μ μ²λ¦¬ μμ μ΄ μνλ©λλ€.
- URL νμΈ: Djangoμ URL νμΈμλ μμ²λ URLμ κ²μ¬νκ³ μ΄λ₯Ό μ²λ¦¬ν μ μ ν λ·° ν¨μλ₯Ό κ²°μ ν©λλ€.
- λ·° μ€ν: μλ³λ λ·° ν¨μκ° μ€νλ©λλ€. μ¬κΈ°μλ μΌλ°μ μΌλ‘ λ°μ΄ν°λ² μ΄μ€μ μνΈ μμ©νκ³ , μλ΅ μ½ν μΈ λ₯Ό μμ±νκ³ , HTTP μλ΅μ μ€λΉνλ μμ μ΄ ν¬ν¨λ©λλ€.
- λ―Έλ€μ¨μ΄ μ²λ¦¬(λ°μ ): μλ΅μ μμμΌλ‘ λ―Έλ€μ¨μ΄ μ€νμ ν΅ν΄ λ€μ μ λ¬λ©λλ€. μ¬κΈ°μμ ν€λ μΆκ°, μλ΅ μμΆ, μΏ ν€ μ€μ κ³Ό κ°μ μμ μ μνν μ μμ΅λλ€.
- WSGI μλ²κ° μλ΅μ 보λ λλ€: WSGI μλ²λ λ§μ§λ§μΌλ‘ HTTP μλ΅μ ν΄λΌμ΄μΈνΈμ λ€μ 보λ λλ€.
Django λ―Έλ€μ¨μ΄λ 무μμ λκΉ?
Django λ―Έλ€μ¨μ΄λ Djangoμ μμ²/μλ΅ μ²λ¦¬μ λν νν¬ νλ μμν¬μ λλ€. Djangoμ μ λ ₯ λλ μΆλ ₯μ μ μμ μΌλ‘ λ³κ²½νλ νλ¬κ·Έ κ°λ₯ν ν΄λμ€ μ§ν©μ λλ€. μΉ μλ²μ λ·° ν¨μ μ¬μ΄μ μμΉνμ¬ μμ²κ³Ό μλ΅μ κ°λ‘μ±μ μμ νλ μΌλ ¨μ νν°λ‘ μκ°νμμμ€.
λ―Έλ€μ¨μ΄λ₯Ό μ¬μ©νλ©΄ λ€μμ μνν μ μμ΅λλ€.
- λ·°μ λλ¬νκΈ° μ μ μμ²μ μμ ν©λλ€(μ: ν€λ μΆκ°, μΈμ¦ μν).
- ν΄λΌμ΄μΈνΈμ 보λ΄κΈ° μ μ μλ΅μ μμ ν©λλ€(μ: ν€λ μΆκ°, μ½ν μΈ μμΆ).
- μμ²μ΄ λ·°μ λλ¬νλλ‘ νμ©ν μ§ κ±°λΆν μ§ κ²°μ ν©λλ€.
- λ·°κ° μ€νλκΈ° μ νμ μμ μ μνν©λλ€(μ: λ‘κΉ , νλ‘νμΌλ§).
Djangoμ κΈ°λ³Έ λ―Έλ€μ¨μ΄λ λ€μκ³Ό κ°μ ν΅μ¬ κΈ°λ₯μ μ²λ¦¬ν©λλ€.
- μΈμ κ΄λ¦¬
- μΈμ¦
- λ©μμ§ νμ(μ: μ±κ³΅ λ° μ€λ₯ λ©μμ§)
- GZIP μμΆ
λ―Έλ€μ¨μ΄λ₯Ό μ¬μ©νλ μ΄μ ? μ₯μ λ° μ΄μ
λ―Έλ€μ¨μ΄λ λ€μκ³Ό κ°μ λͺ κ°μ§ μ€μν μ₯μ μ μ 곡ν©λλ€.
- μ½λ μ¬μ¬μ©μ±: λ―Έλ€μ¨μ΄ λ‘μ§μ μ¬λ¬ λ·°μ νλ‘μ νΈμμ μ¬μ¬μ©ν μ μμΌλ―λ‘ μ€λ³΅ μ½λλ₯Ό λ°©μ§ν μ μμ΅λλ€. μλ₯Ό λ€μ΄ λͺ¨λ λ·°μμ μΈμ¦μ ꡬννλ λμ λ―Έλ€μ¨μ΄λ₯Ό μ¬μ©νμ¬ μ μμ μΌλ‘ μ²λ¦¬ν μ μμ΅λλ€.
- κ΄μ¬μ¬ λΆλ¦¬: μΈμ¦, κΆν λΆμ¬, λ‘κΉ λ° μΊμ±κ³Ό κ°μ κ΅μ°¨ κ΄μ¬μ¬λ₯Ό λ·°μ λΉμ¦λμ€ λ‘μ§κ³Ό λΆλ¦¬νμ¬ κ΄μ¬μ¬λ₯Ό λΆλ¦¬νλ λ° λμμ΄ λ©λλ€. μ΄λ κ² νλ©΄ μ½λκ° λ κΉλνκ³ μ μ§ κ΄λ¦¬κ° μ¬μμ§λ©° μ΄ν΄νκΈ° μ¬μμ§λλ€.
- μ μμ μν₯: λ―Έλ€μ¨μ΄λ λͺ¨λ μμ²κ³Ό μλ΅μ μν₯μ λ―ΈμΉλ―λ‘ μ ν리μΌμ΄μ μ 체μμ μΌκ΄λ λμμ μ μ©νλ κ°λ ₯ν λꡬμ λλ€.
- μ μ°μ± λ° νμ₯μ±: Djangoμ λ―Έλ€μ¨μ΄ μμ€ν μ λ§€μ° μ μ°ν©λλ€. λ―Έλ€μ¨μ΄ κ΅¬μ± μμλ₯Ό μ½κ² μΆκ°, μ κ±° λλ μμ νμ¬ μ ν리μΌμ΄μ μ λμμ μ¬μ©μ μ μν μ μμ΅λλ€. νΉμ νλ‘μ νΈμ λ§κ² μ‘°μ λ λ§€μ° κ΅¬μ²΄μ μΈ μꡬ μ¬νμ ν΄κ²°νκΈ° μν΄ μ¬μ©μ μ μ λ―Έλ€μ¨μ΄λ₯Ό μμ±ν μ μμ΅λλ€.
- μ±λ₯ μ΅μ ν: μΊμ± λ―Έλ€μ¨μ΄μ κ°μ νΉμ λ―Έλ€μ¨μ΄λ λ°μ΄ν°λ² μ΄μ€ λ° μΉ μλ²μ λ‘λλ₯Ό μ€μ¬ μ ν리μΌμ΄μ μ μ±λ₯μ ν¬κ² ν₯μμν¬ μ μμ΅λλ€.
Django λ―Έλ€μ¨μ΄ μλ λ°©μ: μ²λ¦¬ μμ
`settings.py`μμ λ―Έλ€μ¨μ΄ ν΄λμ€κ° μ μλ μμκ° μ€μν©λλ€. Djangoλ νΉμ μμλ‘ λ―Έλ€μ¨μ΄λ₯Ό μ²λ¦¬ν©λλ€. λ¨Όμ μμ² λ¨κ³(μμμ μλλ‘), λ€μμ μλ΅ λ¨κ³(μλμμ μλ‘)μ λλ€.
μμ² λ¨κ³: λ―Έλ€μ¨μ΄λ `MIDDLEWARE` μ€μ μ μ μλ μμλλ‘ λ€μ΄μ€λ μμ²μ μ μ©λ©λλ€.
μλ΅ λ¨κ³: μλ΅μ μμμΌλ‘ λ―Έλ€μ¨μ΄λ₯Ό ν΅κ³Όν©λλ€. μ¦, `MIDDLEWARE` μ€μ μ μ μλ λ§μ§λ§ λ―Έλ€μ¨μ΄κ° μλ΅μ λ¨Όμ μ²λ¦¬νκ³ μ²« λ²μ§Έ λ―Έλ€μ¨μ΄κ° λ§μ§λ§μΌλ‘ μ²λ¦¬ν©λλ€.
μ΄ μμλ₯Ό μ΄ν΄νλ κ²μ λ―Έλ€μ¨μ΄κ° μνΈ μμ©νλ λ°©μμ μ μ΄νκ³ μκΈ°μΉ μμ λμμ λ°©μ§νλ λ° μ€μν©λλ€.
`settings.py`μμ λ―Έλ€μ¨μ΄ ꡬμ±
`settings.py` νμΌμ `MIDDLEWARE` μ€μ μ λ―Έλ€μ¨μ΄μ μ€μ κ΅¬μ± μ§μ μ λλ€. κ° λ¬Έμμ΄μ΄ λ―Έλ€μ¨μ΄ ν΄λμ€μ κ²½λ‘λ₯Ό λνλ΄λ λ¬Έμμ΄ λͺ©λ‘μ λλ€.
λ€μμ λ¨μνλ μμ λλ€.
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
μ΄ κ΅¬μ±μλ νμ μμ μ μ²λ¦¬νλ Djangoμ κΈ°λ³Έ λ―Έλ€μ¨μ΄κ° ν¬ν¨λμ΄ μμ΅λλ€. κΈ°μ‘΄ λ―Έλ€μ¨μ΄μ κ΄λ ¨λ μ¬λ°λ₯Έ μμλ‘ λ―Έλ€μ¨μ΄ ν΄λμ€ κ²½λ‘λ₯Ό μ΄ λͺ©λ‘μ μΆκ°νμ¬ μ¬μ©μ μ μ λ―Έλ€μ¨μ΄λ₯Ό μΆκ°ν μ μμ΅λλ€.
μ¬μ©μ μ μ Django λ―Έλ€μ¨μ΄ μμ±
μ¬μ©μ μ μ λ―Έλ€μ¨μ΄λ₯Ό λ§λ€λ €λ©΄ μμ²/μλ΅ μ£ΌκΈ°λ₯Ό κ°λ‘μ±μ μμ νλ νΉμ λ©μλκ° μλ Python ν΄λμ€λ₯Ό μ μν΄μΌ ν©λλ€. ꡬνν μ μλ μ£Όμ λ©μλλ λ€μκ³Ό κ°μ΅λλ€.
- `__init__(self, get_response)`: λ―Έλ€μ¨μ΄κ° μ΄κΈ°νλ λ ν λ²λ§ νΈμΆλ©λλ€. μΌλ°μ μΌλ‘ νΈμΆ κ°λ₯ν `get_response`λ₯Ό λμ€μ μ¬μ©νκΈ° μν΄ μΈμ€ν΄μ€ λ³μλ‘ μ μ₯ν©λλ€. μ΄ λ§€κ°λ³μλ 체μΈμ λ€μ λ―Έλ€μ¨μ΄λ₯Ό λνλ΄κ±°λ λ§μ§λ§ λ―Έλ€μ¨μ΄μΈ κ²½μ° λ·° ν¨μλ₯Ό λνλ λλ€.
- `__call__(self, request)`: μ΄ λ©μλλ κ° μμ²μμ νΈμΆλ©λλ€. μ²λ¦¬ μν μ₯μμΈ λ―Έλ€μ¨μ΄μ ν΅μ¬μ λλ€. μμ² κ°μ²΄λ₯Ό μ λ ₯μΌλ‘ λ°κ³ `HttpResponse` κ°μ²΄ λλ `get_response(request)` νΈμΆ κ²°κ³Όλ₯Ό λ°νν΄μΌ ν©λλ€.
- `process_request(self, request)`: λ·°κ° νΈμΆλκΈ° μ μ νΈμΆλ©λλ€. μμ² κ°μ²΄λ₯Ό λ°μ΅λλ€. `request` κ°μ²΄λ₯Ό μμ νκ±°λ `HttpResponse`λ₯Ό λ°ννμ¬ μμ²μ λ¨μΆν μ μμ΅λλ€. `None`μ λ°ννλ©΄ μμ²μ λ€μ λ―Έλ€μ¨μ΄ λλ λ·°λ‘ μ§νλ©λλ€.
- `process_view(self, request, view_func, view_args, view_kwargs)`: Djangoκ° λ·°λ₯Ό νΈμΆνκΈ° μ§μ μ νΈμΆλ©λλ€. `request` κ°μ²΄, λ·° ν¨μ λ° λ·°μ μ λ¬λ λͺ¨λ μΈμλ₯Ό λ°μ΅λλ€. μμ² λλ λ·°μ μΈμλ₯Ό μμ ν μ μμ΅λλ€. `HttpResponse`λ₯Ό λ°ννλ©΄ νλ‘μΈμ€κ° λ¨μΆλ©λλ€.
- `process_response(self, request, response)`: λ·°κ° νΈμΆλκ³ μλ΅μ΄ μμ±λ νμ νΈμΆλ©λλ€. `request` κ°μ²΄μ `response` κ°μ²΄λ₯Ό λ°μ΅λλ€. `response` κ°μ²΄λ₯Ό μμ ν μ μμ΅λλ€. `response` κ°μ²΄(μμ λμκ±°λ μμ λμ§ μμ)λ₯Ό λ°νν΄μΌ ν©λλ€.
- `process_exception(self, request, exception)`: μμ² μ²λ¦¬ μ€(λ―Έλ€μ¨μ΄ λλ λ·°μμ) μμΈκ° λ°μνλ©΄ νΈμΆλ©λλ€. `request` κ°μ²΄μ μμΈ κ°μ²΄λ₯Ό λ°μ΅λλ€. `HttpResponse`λ₯Ό λ°ννμ¬ μμΈλ₯Ό μ²λ¦¬νκ³ νλ‘μΈμ€λ₯Ό λ¨μΆνκ±°λ `None`μ λ°ννμ¬ Djangoκ° κΈ°λ³Έ λ°©μμΌλ‘ μμΈλ₯Ό μ²λ¦¬νλλ‘ ν μ μμ΅λλ€.
μ: κ°λ¨ν μ¬μ©μ μ μ λ―Έλ€μ¨μ΄(μμ² λ‘κΉ )
λ€μ΄μ€λ λͺ¨λ μμ²μ κΈ°λ‘νλ λ―Έλ€μ¨μ΄λ₯Ό λ§λ€μ΄ λ³΄κ² μ΅λλ€. Django μ±μμ `middleware.py`λΌλ νμΌμ λ§λλλ€.
# In myapp/middleware.py
import logging
logger = logging.getLogger(__name__)
class RequestLoggingMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# Code to be executed for each request before the view is called
logger.info(f'Request received: {request.method} {request.path}')
response = self.get_response(request)
# Code to be executed for each request/response after the view is called
return response
κ·Έλ° λ€μ μ΄ λ―Έλ€μ¨μ΄λ₯Ό `settings.py`μ μΆκ°ν©λλ€.
MIDDLEWARE = [
# ... other middleware ...
'myapp.middleware.RequestLoggingMiddleware',
]
μ΄μ μμ²μ΄ λ€μ΄μ¬ λλ§λ€ λ―Έλ€μ¨μ΄λ μμ² λ©μλμ κ²½λ‘λ₯Ό λ‘κ·Έμ κΈ°λ‘ν©λλ€.
μ: μμ² ν€λ μμ
λ€μμ λͺ¨λ μλ΅μ μ¬μ©μ μ μ ν€λλ₯Ό μΆκ°νλ λ―Έλ€μ¨μ΄μ μμ λλ€.
# In myapp/middleware.py
class AddCustomHeaderMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
response['X-Custom-Header'] = 'Hello from Middleware!'
return response
`settings.py`μ `MIDDLEWARE` λͺ©λ‘μ μ΄λ₯Ό μΆκ°νλ κ²μ μμ§ λ§μμμ€.
Django λ―Έλ€μ¨μ΄μ μΌλ°μ μΈ μ¬μ© μ¬λ‘ λ° μ
λ―Έλ€μ¨μ΄λ λ€μ¬λ€λ₯ν©λλ€. λ€μμ λͺ κ°μ§ μΌλ°μ μΈ μ¬μ© μ¬λ‘ λ° μμ λλ€.
- μΈμ¦ λ° κΆν λΆμ¬: νΉμ λ·°μ λν μ‘μΈμ€λ₯Ό νμ©νκΈ° μ μ μ¬μ©μ μ격 μ¦λͺ λ° μ‘μΈμ€ κΆνμ νμΈν©λλ€. Djangoμ `AuthenticationMiddleware`κ° μ΄λ₯Ό μ²λ¦¬ν©λλ€. μ¬μ©μ μ μ λ―Έλ€μ¨μ΄λ μ΄λ₯Ό νμ₯νμ¬ λ€μν μΈμ¦ λ°©λ²(μ: API ν€, OAuth)μ μ§μνκ±°λ μν κΈ°λ° μ‘μΈμ€ μ μ΄λ₯Ό ꡬνν μ μμ΅λλ€.
- μΈμ κ΄λ¦¬: μ¬μ©μλ³ λ°μ΄ν°λ₯Ό μ μ₯νκ³ κ²μνκΈ° μν΄ μ¬μ©μ μΈμ μ μ²λ¦¬ν©λλ€. Djangoμ `SessionMiddleware`κ° κΈ°λ³Έμ μΌλ‘ μ΄λ₯Ό μ²λ¦¬ν©λλ€.
- CSRF 보νΈ: κ΅μ°¨ μ¬μ΄νΈ μμ² μμ‘° 곡격μΌλ‘λΆν° 보νΈν©λλ€. Djangoμ `CsrfViewMiddleware`κ° CSRF 보νΈλ₯Ό ꡬνν©λλ€.
- GZIP μμΆ: λμν μ¬μ©λμ μ€μ΄κ³ νμ΄μ§ λ‘λ μκ°μ κ°μ νκΈ° μν΄ μλ΅μ μμΆν©λλ€. Djangoμ `GZipMiddleware`κ° μ΄λ₯Ό μ²λ¦¬ν©λλ€.
- λ‘κΉ λ° λͺ¨λν°λ§: μμ², μ€λ₯ λ° μ±λ₯ λ©νΈλ¦μ κΈ°λ‘ν©λλ€. μ΄μ μμ μμλ μμ² λ‘κΉ μ 보μ¬μ£Όμμ΅λλ€. λ―Έλ€μ¨μ΄λ₯Ό μ¬μ©νμ¬ λͺ¨λν°λ§ λꡬμ ν΅ν©ν μ μμ΅λλ€.
- μ½ν μΈ λ³΄μ μ μ± (CSP): λ€μν μΉ μ·¨μ½μ±μΌλ‘λΆν° 보νΈνκΈ° μν΄ λ³΄μ ν€λλ₯Ό μ€μ ν©λλ€. λ―Έλ€μ¨μ΄λ λΈλΌμ°μ μμ λ‘λν μ μλ μ½ν μΈ μμ€λ₯Ό μ ννκΈ° μν΄ `Content-Security-Policy` ν€λλ₯Ό μ€μ ν μ μμ΅λλ€.
- μΊμ±: μμ£Ό μ‘μΈμ€νλ λ°μ΄ν°λ₯Ό μΊμ±νμ¬ μ±λ₯μ κ°μ ν©λλ€. Djangoμ κΈ°λ³Έ μΊμ± νλ μμν¬ λ° νμ¬ λ―Έλ€μ¨μ΄κ° μ΄ κΈ°λ₯μ μ 곡ν©λλ€.
- URL 리λλ μ : νΉμ 쑰건(μ: μ¬μ©μ λ‘μΌμΌ, μ₯μΉ μ ν)μ λ°λΌ μ¬μ©μλ₯Ό λ€λ₯Έ URLλ‘ λ¦¬λλ μ ν©λλ€.
- μμ² μμ : μμ² κ°μ²΄λ₯Ό μμ ν©λλ€(μ: ν€λ μΆκ°, μμ² μμ± μ€μ ). μ΄λ μ ν리μΌμ΄μ μ΄ νλ‘μ λ€μμ μ€νλλ κ²½μ° `REMOTE_ADDR`μ μ€μ νλ κ²κ³Ό κ°μ μμ μ μΌλ°μ μΌλ‘ μ¬μ©λ©λλ€.
- μλ΅ μμ : μλ΅ κ°μ²΄λ₯Ό μμ ν©λλ€(μ: ν€λ μΆκ°, μ½ν μΈ μμ ).
- μλ μ ν: μ μ©μ λ°©μ§νκΈ° μν΄ νΉμ IP μ£Όμμμ μ€λ μμ² μλ₯Ό μ νν©λλ€.
- κ΅μ ν(i18n) λ° μ§μν(l10n): μ¬μ©μ κΈ°λ³Έ μ€μ λλ λΈλΌμ°μ μ€μ μ κΈ°λ°μΌλ‘ μμ²μ λν μΈμ΄ λ° λ‘μΌμΌμ μ€μ ν©λλ€. Djangoμ `LocaleMiddleware`κ° μ΄λ₯Ό μ²λ¦¬ν©λλ€.
μ: κΈ°λ³Έ μΈμ¦ ꡬν
λͺ¨λ νμ΄μ§μ μ‘μΈμ€νλ €λ©΄ μ¬μ©μ μ΄λ¦κ³Ό μνΈκ° νμν λ―Έλ€μ¨μ΄λ₯Ό λ§λ€μ΄ λ³΄κ² μ΅λλ€(λ°λͺ¨ λͺ©μ μΌλ‘, μ μ ν 보μ κ³ λ € μ¬ν μμ΄ νλ‘λμ μμ μ¬μ©νμ§ λ§μμμ€).
# In myapp/middleware.py
from django.http import HttpResponse
from django.contrib.auth import authenticate, login
class BasicAuthMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
if not request.user.is_authenticated:
auth_header = request.META.get('HTTP_AUTHORIZATION')
if auth_header:
try:
auth_type, auth_string = auth_header.split(' ', 1)
if auth_type.lower() == 'basic':
import base64
auth_decoded = base64.b64decode(auth_string).decode('utf-8')
username, password = auth_decoded.split(':', 1)
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
else:
return HttpResponse('Unauthorized', status=401, headers={'WWW-Authenticate': 'Basic realm="Restricted Area"'})
except Exception:
return HttpResponse('Unauthorized', status=401, headers={'WWW-Authenticate': 'Basic realm="Restricted Area"'})
else:
return HttpResponse('Unauthorized', status=401, headers={'WWW-Authenticate': 'Basic realm="Restricted Area"'})
return self.get_response(request)
`settings.py`μμ μ΄λ₯Ό `MIDDLEWARE`μ μΆκ°ν©λλ€.
MIDDLEWARE = [
# ... other middleware ...
'myapp.middleware.BasicAuthMiddleware',
]
μ΄ λ―Έλ€μ¨μ΄λ κ° μμ²μμ κΈ°λ³Έ μΈμ¦ ν€λλ₯Ό νμΈν©λλ€. ν€λκ° μμΌλ©΄ μ¬μ©μλ₯Ό μΈμ¦νλ €κ³ μλν©λλ€. μΈμ¦μ μ€ν¨νλ©΄ "Unauthorized" μλ΅μ λ°νν©λλ€. μΈμ¦μ μ±κ³΅νλ©΄ μμ²μ΄ λ·°λ‘ μ λ¬λλλ‘ ν©λλ€.
μ: μμ² μλ μ ν ꡬν
μλ μ νμ μ μ©μ λ°©μ§νκ³ μλ²κ° κ³ΌλΆνλλ κ²μ λ°©μ§νλ λ° λμμ΄ λ©λλ€. λ€μ μμ μμλ λ¨μνλ ꡬνμ μ 곡ν©λλ€.
# In myapp/middleware.py
import time
from django.http import HttpResponse, HttpResponseTooManyRequests
from django.conf import settings
class RateLimitMiddleware:
def __init__(self, get_response):
self.get_response = get_response
self.requests = {}
def __call__(self, request):
ip_address = self.get_client_ip(request)
now = time.time()
if ip_address:
if ip_address not in self.requests:
self.requests[ip_address] = {
'count': 0,
'last_request': now
}
if settings.RATE_LIMIT_WINDOW:
if now - self.requests[ip_address]['last_request'] > settings.RATE_LIMIT_WINDOW:
self.requests[ip_address]['count'] = 0
self.requests[ip_address]['last_request'] = now
self.requests[ip_address]['count'] += 1
self.requests[ip_address]['last_request'] = now
if settings.RATE_LIMIT_REQUESTS and self.requests[ip_address]['count'] > settings.RATE_LIMIT_REQUESTS:
return HttpResponseTooManyRequests('Too many requests.')
return self.get_response(request)
def get_client_ip(self, request):
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
if x_forwarded_for:
ip = x_forwarded_for.split(',')[0].strip()
else:
ip = request.META.get('REMOTE_ADDR')
return ip
`settings.py`μμ λ€μ μ€μ μ μ μν©λλ€.
RATE_LIMIT_REQUESTS = 10 # Max requests per window
RATE_LIMIT_WINDOW = 60 # Seconds
μ΄λ₯Ό `MIDDLEWARE`μ μΆκ°ν©λλ€.
MIDDLEWARE = [
# ... other middleware ...
'myapp.middleware.RateLimitMiddleware',
]
μ΄ λ―Έλ€μ¨μ΄λ ν΄λΌμ΄μΈνΈμ IP μ£Όμλ₯Ό κΈ°λ°μΌλ‘ μμ²μ μ νν©λλ€. `RATE_LIMIT_REQUESTS` λ° `RATE_LIMIT_WINDOW`λ₯Ό μ‘°μ νμ¬ μλ μ νμ ꡬμ±ν©λλ€.
Django λ―Έλ€μ¨μ΄ κ°λ°μ μν λͺ¨λ² μ¬λ‘
λ€μ λͺ¨λ² μ¬λ‘λ₯Ό λ°λ₯΄λ©΄ λ―Έλ€μ¨μ΄κ° ν¨κ³Όμ μ΄κ³ μ μ§ κ΄λ¦¬κ° κ°λ₯νλ©° μ±λ₯ λ³λͺ© νμμ΄ λ°μνμ§ μμ΅λλ€.
- κ°λ¨νκ² μ μ§νμμμ€: λ―Έλ€μ¨μ΄λ νΉμ νκ³ μ μ μλ μμ μ μ§μ€ν΄μΌ ν©λλ€. 볡μ‘ν λ‘μ§μ΄λ κ³Όλν μ’ μμ±μ νΌνμμμ€.
- μ±λ₯μ΄ λ°μ΄λμΌ ν©λλ€: λ―Έλ€μ¨μ΄λ λͺ¨λ μμ²/μλ΅μμ μ€νλ©λλ€. μ²λ¦¬ μκ°μ μ΅μννλλ‘ μ½λλ₯Ό μ΅μ ννμμμ€. λ―Έλ€μ¨μ΄ λ΄μμ μ°¨λ¨ μμ λλ λΆνμν λ°μ΄ν°λ² μ΄μ€ 쿼리λ₯Ό νΌνμμμ€.
- μ² μ νκ² ν μ€νΈνμμμ€: λ¨μ ν μ€νΈλ₯Ό μμ±νμ¬ λ―Έλ€μ¨μ΄κ° μ¬λ°λ₯΄κ² μλνκ³ λ€μν μλ리μ€μμ μμλλ‘ μλνλμ§ νμΈνμμμ€. μ£μ§ μΌμ΄μ€ λ° μ€λ₯ μ²λ¦¬λ₯Ό ν μ€νΈνμμμ€.
- λͺ ννκ² λ¬Έμννμμμ€: λ―Έλ€μ¨μ΄κ° μννλ μμ , μλ λ°©μ λ° κ΅¬μ± λ°©λ²μ λν λͺ νν λ¬Έμλ₯Ό μ 곡νμμμ€. μμ λ° μ¬μ© μ§μΉ¨μ ν¬ν¨νμμμ€.
- Django κ·μΉμ λ°λ₯΄μμμ€: Djangoμ μ½λ© μ€νμΌ λ° κ·μΉμ μ€μνμμμ€. μ΄λ κ² νλ©΄ μ½λλ₯Ό λ μ½κΈ° μ½κ³ λ€λ₯Έ κ°λ°μκ° μ΄ν΄νκΈ° μ¬μμ§λλ€.
- μ±λ₯μ λ―ΈμΉλ μν₯ κ³ λ €: λ―Έλ€μ¨μ΄μ μ μ¬μ μ±λ₯ μν₯μ μ μ€νκ² νκ°νμμμ€. νΉν 리μμ€ μ§μ½μ μΈ μμ κ³Ό κ΄λ ¨λ κ²½μ° λμ± κ·Έλ μ΅λλ€.
- μμΈλ₯Ό μ μμ μΌλ‘ μ²λ¦¬νμμμ€: μ μ ν μ€λ₯ μ²λ¦¬λ₯Ό ꡬννμ¬ λ―Έλ€μ¨μ΄κ° μ ν리μΌμ΄μ μ μ€λ¨μν€μ§ μλλ‘ νμμμ€. `try...except` λΈλ‘μ μ¬μ©νμ¬ μ μ¬μ μΈ μμΈλ₯Ό ν¬μ°©νκ³ μ€λ₯λ₯Ό κΈ°λ‘νμμμ€. ν¬κ΄μ μΈ μμΈ μ²λ¦¬λ₯Ό μν΄ `process_exception()`μ μ¬μ©νμμμ€.
- μμκ° μ€μν©λλ€: `MIDDLEWARE` μ€μ μμ λ―Έλ€μ¨μ΄ μμλ₯Ό μ μ€νκ² κ³ λ €νμμμ€. μνλ λμμ λ¬μ±νκ³ μΆ©λμ νΌνκΈ° μν΄ λ―Έλ€μ¨μ΄κ° μ¬λ°λ₯Έ μμλ‘ λ°°μΉλμλμ§ νμΈνμμμ€.
- λΆνμνκ² μμ²/μλ΅μ μμ νμ§ λ§μμμ€: μνλ λμμ λ¬μ±νλ λ° νμν κ²½μ°μλ§ μμ²/μλ΅ κ°μ²΄λ₯Ό μμ νμμμ€. λΆνμν μμ μ μ±λ₯ λ¬Έμ λ‘ μ΄μ΄μ§ μ μμ΅λλ€.
κ³ κΈ λ―Έλ€μ¨μ΄ κΈ°μ λ° κ³ λ € μ¬ν
κΈ°λ³Έ μ¬ν μΈμλ λͺ κ°μ§ κ³ κΈ κΈ°μ μ΄ μμ΅λλ€.
- λΉλκΈ° μμ μ λ―Έλ€μ¨μ΄ μ¬μ©: λ―Έλ€μ¨μ΄λ₯Ό μ¬μ©νμ¬ μ΄λ©μΌ 보λ΄κΈ° λλ λ°±κ·ΈλΌμ΄λμμ λ°μ΄ν° μ²λ¦¬μ κ°μ λΉλκΈ° μμ μ μμν μ μμ΅λλ€. Celery λλ κΈ°ν μμ λκΈ°μ΄μ μ¬μ©νμ¬ μ΄λ¬ν μμ μ μ²λ¦¬νμμμ€.
- λ―Έλ€μ¨μ΄ ν©ν 리: λ 볡μ‘ν ꡬμ±μ κ²½μ° κ΅¬μ± μΈμλ₯Ό μ¬μ©νκ³ λ―Έλ€μ¨μ΄ ν΄λμ€λ₯Ό λ°ννλ ν¨μμΈ λ―Έλ€μ¨μ΄ ν©ν 리λ₯Ό μ¬μ©ν μ μμ΅λλ€. μ΄λ `settings.py`μ μ μλ λ§€κ°λ³μλ‘ λ―Έλ€μ¨μ΄λ₯Ό μ΄κΈ°νν΄μΌ νλ κ²½μ°μ μ μ©ν©λλ€.
- μ‘°κ±΄λΆ λ―Έλ€μ¨μ΄: μ€μ λλ νκ²½ λ³μλ₯Ό κΈ°λ°μΌλ‘ λ―Έλ€μ¨μ΄λ₯Ό 쑰건λΆλ‘ νμ±ννκ±°λ λΉνμ±νν μ μμ΅λλ€. μ΄λ₯Ό ν΅ν΄ λ€μν νκ²½(μ: κ°λ°, ν μ€νΈ, νλ‘λμ )μ λ§κ² μ ν리μΌμ΄μ μ λμμ μ‘°μ ν μ μμ΅λλ€.
- API μλ μ νμ μν λ―Έλ€μ¨μ΄: API μλν¬μΈνΈμ λν μ κ΅ν μλ μ ν κΈ°μ μ ꡬνν©λλ€. μλ μ ν λ°μ΄ν°λ₯Ό μ μ₯νκΈ° μν΄ Redisμ κ°μ νμ¬ λΌμ΄λΈλ¬λ¦¬ λλ νΉμ μλΉμ€λ₯Ό μ¬μ©νλ κ²μ κ³ λ €νμμμ€.
- νμ¬ λΌμ΄λΈλ¬λ¦¬μ ν΅ν©: λ―Έλ€μ¨μ΄λ₯Ό νμ¬ λΌμ΄λΈλ¬λ¦¬ λ° λꡬμ μννκ² ν΅ν©ν μ μμ΅λλ€. μλ₯Ό λ€μ΄ λͺ¨λν°λ§ λꡬμ ν΅ν©νμ¬ λ©νΈλ¦μ μμ§νκ³ μ±λ₯μ μΆμ ν©λλ€.
μ: λ―Έλ€μ¨μ΄ ν©ν 리 μ¬μ©
μ΄ μμ μμλ κ°λ¨ν λ―Έλ€μ¨μ΄ ν©ν 리λ₯Ό 보μ¬μ€λλ€. μ΄ μ κ·Ό λ°©μμ μ¬μ©νλ©΄ `settings.py` νμΌμμ κ΅¬μ± λ§€κ°λ³μλ₯Ό μ λ¬ν μ μμ΅λλ€.
# In myapp/middleware.py
from django.conf import settings
def my_middleware_factory(setting_key):
class MyConfigurableMiddleware:
def __init__(self, get_response):
self.get_response = get_response
self.config_value = settings.get(setting_key, 'default_value') # Read config
def __call__(self, request):
# Use self.config_value
print(f'Config value: {self.config_value}')
return self.get_response(request)
return MyConfigurableMiddleware
`settings.py`μμ λ€μκ³Ό κ°μ΄ ꡬμ±ν©λλ€.
MIDDLEWARE = [
# ... other middleware ...
'myapp.middleware.my_middleware_factory', # Note: Pass it without parenthesis or arguments.
]
MY_CUSTOM_SETTING = 'some_value'
κ·Έλ¦¬κ³ `urls.py` λλ λ―Έλ€μ¨μ΄κ° μ¬μ©λλ λ€λ₯Έ λͺ¨λ μμΉμμ κ΅¬μ± μ€μ μ ν©ν 리 λ©μλμ μ λ¬ν μ μμ΅λλ€.
from myapp.middleware import my_middleware_factory
urlpatterns = [
# ...other url patterns...
# No arguments needed for the factory method in URL configuration
]
μ΄ μ κ·Ό λ°©μμ μ μ°μ±κ³Ό μ¬μ©μ μ μλ₯Ό ν₯μμν΅λλ€.
μΌλ°μ μΈ λ¬Έμ λ° λ¬Έμ ν΄κ²°
λ€μμ Django λ―Έλ€μ¨μ΄λ₯Ό μ¬μ©ν λ λ°μν μ μλ λͺ κ°μ§ μΌλ°μ μΈ λ¬Έμ μ ν΄κ²° λ°©λ²μ λλ€.
- μλͺ»λ λ―Έλ€μ¨μ΄ μμ: λ―Έλ€μ¨μ΄κ° μμλλ‘ μλνμ§ μμΌλ©΄ `settings.py`μμ μμλ₯Ό λ€μ νμΈνμμμ€. μμκ° μ€μν©λλ€.
- μμ² μ²λ¦¬ μ€ μ€λ₯: λ―Έλ€μ¨μ΄μμ μ€λ₯κ° λ°μνλ©΄ μ 체 μμ² μ£ΌκΈ°κ° μ€λ¨λ μ μμ΅λλ€. `process_exception()` λ©μλλ₯Ό μ¬μ©νμ¬ μμΈλ₯Ό μ μμ μΌλ‘ μ²λ¦¬νκ³ μκΈ°μΉ μμ μ€λ₯λ₯Ό λ°©μ§νμμμ€. λν λ―Έλ€μ¨μ΄μ μν μ’ μμ±μ΄ μλμ§ νμΈνμμμ€.
- μ±λ₯ λ³λͺ© νμ: λΉν¨μ¨μ μΈ λ―Έλ€μ¨μ΄λ μ ν리μΌμ΄μ μλλ₯Ό μ νμν¬ μ μμ΅λλ€. μ½λλ₯Ό νλ‘νμΌλ§νμ¬ μ±λ₯ λ³λͺ© νμμ μλ³νκ³ κ·Έμ λ°λΌ μ΅μ ννμμμ€. λ―Έλ€μ¨μ΄ λ΄μμ 리μμ€ μ§μ½μ μΈ μμ μ νΌνκ±°λ λ°±κ·ΈλΌμ΄λ μμ μ μμνμμμ€.
- λ€λ₯Έ λ―Έλ€μ¨μ΄μμ μΆ©λ: λ―Έλ€μ¨μ΄κ° νλ‘μ νΈμ λ€λ₯Έ λ―Έλ€μ¨μ΄ λλ Djangoμ κΈ°λ³Έ λ―Έλ€μ¨μ΄μ μΆ©λν μ μλ€λ μ μ λͺ μ¬νμμμ€. μ€λͺ μλ₯Ό μ μ€νκ² κ²ν νκ³ λͺ¨λ λ―Έλ€μ¨μ΄κ° μ¬λ°λ₯΄κ² μνΈ μμ©νλμ§ νμΈνμμμ€.
- μλνμ§ μμ λΆμμ©: λ―Έλ€μ¨μ΄κ° μλν λ°©μμΌλ‘λ§ μμ²/μλ΅ κ°μ²΄λ₯Ό μμ νλμ§ νμΈνμμμ€. μκΈ°μΉ μμ λμμΌλ‘ μ΄μ΄μ§ μ μλ μλνμ§ μμ λΆμμ©μ νΌνμμμ€.
- μΈμ λ¬Έμ : μΈμ κ΄λ ¨ λ¬Έμ κ° μλ κ²½μ° `SessionMiddleware`κ° `settings.py` νμΌμμ μ¬λ°λ₯΄κ² ꡬμ±λμκ³ μΈμ λ°μ΄ν°κ° μ¬λ°λ₯΄κ² μ μ₯λκ³ μ‘μΈμ€λλμ§ νμΈνμμμ€.
- CSRF ν ν° λ¬Έμ : CSRF ν ν° κ΄λ ¨ λ¬Έμ κ° μλ κ²½μ° `CsrfViewMiddleware`κ° `settings.py`μ μ¬λ°λ₯΄κ² μλμ§ νμΈνμμμ€. λν μ¬λ°λ₯Έ CSRF ν ν° λ λλ§μ μν΄ μμμ λ€μ νμΈνμμμ€.
Djangoμ κΈ°λ³Έ μ 곡 λλ²κΉ λꡬ λ° λ‘κΉ μ μ¬μ©νμ¬ λ¬Έμ λ₯Ό μΆμ νμμμ€. μμ²/μλ΅ λΌμ΄νμ¬μ΄ν΄μ λΆμνμ¬ λ¬Έμ μ κ·Όλ³Έ μμΈμ μλ³νμμμ€. λ°°ν¬νκΈ° μ μ λ―Έλ€μ¨μ΄λ₯Ό μ² μ ν ν μ€νΈνλ κ²λ μ€μν©λλ€.
κ²°λ‘ : Django λ―Έλ€μ¨μ΄ λ§μ€ν°νκΈ°
Django λ―Έλ€μ¨μ΄λ λͺ¨λ Django κ°λ°μμκ² κΈ°λ³Έμ μΈ κ°λ μ λλ€. μλ λ°©μ, κ΅¬μ± λ°©λ² λ° μ¬μ©μ μ μ λ―Έλ€μ¨μ΄λ₯Ό λ§λλ λ°©λ²μ μ΄ν΄νλ κ²μ κ°λ ₯νκ³ μ μ§ κ΄λ¦¬κ° κ°λ₯νλ©° νμ₯ κ°λ₯ν μΉ μ ν리μΌμ΄μ μ ꡬμΆνλ λ° μ€μν©λλ€.
λ―Έλ€μ¨μ΄λ₯Ό λ§μ€ν°ν¨μΌλ‘μ¨ μ ν리μΌμ΄μ μ μμ² μ²λ¦¬ νμ΄νλΌμΈμ κ°λ ₯νκ² μ μ΄ν μ μμΌλ―λ‘ μΈμ¦ λ° κΆν λΆμ¬μμ μ±λ₯ μ΅μ ν λ° λ³΄μ κ°νμ μ΄λ₯΄κΈ°κΉμ§ κ΄λ²μν κΈ°λ₯μ ꡬνν μ μμ΅λλ€.
νλ‘μ νΈμ 볡μ‘μ±μ΄ μ¦κ°ν¨μ λ°λΌ λ―Έλ€μ¨μ΄λ₯Ό ν¨κ³Όμ μΌλ‘ μ¬μ©νλ λ₯λ ₯μ νμμ μΈ κΈ°μ μ΄ λ κ²μ λλ€. κ³μ μ°μ΅νκ³ μ€ννλ©΄ Djangoμ λ―Έλ€μ¨μ΄ μμ€ν μ νμ νμ©νλ λ° λ₯μν΄μ§ κ²μ λλ€.